home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / sound / rsynth22.zip / HPLAY.C < prev    next >
Text File  |  1996-09-13  |  8KB  |  326 lines

  1. #include <config.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <float.h>
  5. #define INCL_DOSPROCESS
  6. #define INCL_DOSSEMAPHORES
  7. #include <os2.h>
  8. #define  INCL_OS2MM
  9. #include <os2me.h>
  10. #include "proto.h"
  11. #include "getargs.h"
  12. #include "hplay.h"
  13.  
  14. /* PlayList Entry */
  15.  
  16. typedef struct _PLE {
  17.     ULONG operation;
  18.     ULONG operand1;
  19.     ULONG operand2;
  20.     ULONG operand3;
  21. }PLE;
  22.  
  23. long samp_rate  = 8000;
  24. long bits = 8;
  25. int quiet = FALSE;
  26.  
  27. static unsigned long sem = 0;
  28. static unsigned long tid = 0;
  29.  
  30. struct PlayDataList
  31. {
  32.     unsigned char *charbuff;
  33.     unsigned short *shortbuff;    
  34.     int n;
  35.     struct PlayDataList *next;
  36. };
  37.  
  38. static struct PlayDataList *List=0;
  39.  
  40. void mci_err(ULONG rc)
  41. {
  42.     const rsize = 128;
  43.     char rbuff[rsize];
  44.  
  45.     ULONG rc2 = mciGetErrorString(rc,      // error code
  46.                                   rbuff,   // return buffer
  47.                                   rsize);  // rbuff size
  48.  
  49.     if (rc2 == MCIERR_SUCCESS)
  50.         fprintf(stderr,"MCI error: %s\n\n",rbuff);
  51.     else
  52.         fprintf(stderr,"error # %d has occured!\n\n", rc);
  53. }
  54.  
  55. void playbuf( void *playbuf, int n)
  56. {
  57.  MCI_PLAY_PARMS mpp;
  58.  MCI_GENERIC_PARMS mgp;
  59.  MCI_WAVE_SET_PARMS wsp;
  60.  ULONG rc;
  61.  MCI_OPEN_PARMS mop;
  62.  PLE playlist[2];
  63.  
  64.  if(playbuf)
  65.    {
  66.     playlist[0].operation = DATA_OPERATION;
  67.     playlist[0].operand1  = (long) playbuf;
  68.     playlist[0].operand2  = n;
  69.  
  70.     if(bits == 16) playlist[0].operand2 = n*2;
  71.  
  72.     playlist[0].operand3  = 0;
  73.     playlist[1].operation = EXIT_OPERATION;
  74.     mop.hwndCallback   = 0;
  75.     mop.usDeviceID     = 0;
  76.     mop.pszDeviceType  = MCI_DEVTYPE_WAVEFORM_AUDIO_NAME;
  77.     mop.pszElementName = (void *)&playlist[0];
  78.  
  79.     rc = mciSendCommand(0,
  80.                        MCI_OPEN,                        // open message
  81.                        MCI_WAIT | MCI_OPEN_SHAREABLE |  // message flags
  82.                        MCI_OPEN_PLAYLIST,
  83.                        &mop,                            // parameters
  84.                        0);
  85.  
  86.     if (rc != MCIERR_SUCCESS) mci_err(rc);
  87.  
  88.     // set device parameters
  89.     wsp.hwndCallback    = 0;
  90.     wsp.ulSamplesPerSec = samp_rate;
  91.     wsp.usBitsPerSample = bits;
  92.     wsp.usChannels = 1;
  93.  
  94.     rc = mciSendCommand(mop.usDeviceID,
  95.                        MCI_SET,
  96.                        MCI_WAIT |
  97.                        MCI_WAVE_SET_SAMPLESPERSEC, 
  98.                        &wsp,
  99.                        0);
  100.     if (rc != MCIERR_SUCCESS) mci_err(rc);
  101.     mpp.hwndCallback = 0;
  102.  
  103.     rc = mciSendCommand(mop.usDeviceID,
  104.                        MCI_SET,
  105.                        MCI_WAIT |
  106.                        MCI_WAVE_SET_BITSPERSAMPLE, 
  107.                        &wsp,
  108.                        0);
  109.     if (rc != MCIERR_SUCCESS) mci_err(rc);
  110.     mpp.hwndCallback = 0;
  111.  
  112.     rc = mciSendCommand(mop.usDeviceID,
  113.                        MCI_SET,
  114.                        MCI_WAIT |
  115.                        MCI_WAVE_SET_CHANNELS, 
  116.                        &wsp,
  117.                        0);
  118.  
  119.     if (rc != MCIERR_SUCCESS) mci_err(rc);
  120.     mpp.hwndCallback = 0;
  121.  
  122.     rc = mciSendCommand(mop.usDeviceID,
  123.                         MCI_PLAY,
  124.                         MCI_WAIT,
  125.                         &mpp,
  126.                         0);
  127.     if (rc != MCIERR_SUCCESS) mci_err(rc);
  128.      
  129.     // close device
  130.  
  131.     mgp.hwndCallback = 0;
  132.     rc = mciSendCommand(mop.usDeviceID,
  133.                         MCI_CLOSE,
  134.                         MCI_WAIT,
  135.                         &mgp,
  136.                         0);
  137.  
  138.     if (rc != MCIERR_SUCCESS) mci_err(rc);
  139.     free(playbuf);
  140.     _control87(EM_INVALID | EM_DENORMAL | EM_ZERODIVIDE | EM_OVERFLOW | EM_UNDERFLOW | EM_INEXACT, MCW_EM);
  141.  
  142.    }
  143. }
  144.  
  145.  
  146.  
  147. void PlayThread( void *arg)
  148. {
  149.  struct PlayDataList *l=NULL;
  150.  unsigned long timesposted;
  151.  unsigned long rc;
  152.  for(;;)
  153.    {
  154.     rc = DosWaitEventSem(sem, -1);
  155.     if(rc) 
  156.       return;
  157.     rc = DosResetEventSem(sem, ×posted);
  158.     if(!rc || rc == 300)
  159.       {
  160.        while(timesposted)
  161.           {
  162.            if(!l)
  163.              l=List;
  164.            else
  165.              l=l->next;
  166.            if(!l)
  167.              return;
  168.            if(bits == 8)
  169.              playbuf(l->charbuff,l->n);
  170.            else if (bits == 16)
  171.              playbuf(l->shortbuff, l->n);
  172.            timesposted--;
  173.            }
  174.        }
  175.     else 
  176.       return;
  177.     }
  178.  return;
  179. }
  180.  
  181. int
  182. audio_init(int argc, char **argv)
  183. {
  184.  int rate;
  185.  
  186.  rate = 8;
  187.  argc = getargs("Audio Initialization", argc, argv,
  188.                 "r", "%d",  &rate,   "Sample Rate in kHz - 8, 11, 22, or 44",
  189.                 "Q", NULL, &quiet,   "+Q for no sound output (-Q Default)",
  190.                 "b", "%d", &bits, "Chunk size of playback sample 8 (def) or 16", 
  191.                 NULL);
  192.  if (help_only)
  193.   return (argc);
  194.  
  195.  switch(rate)
  196.     {
  197.      case  8 : samp_rate =  8000;
  198.                break;
  199.      case 11 : samp_rate = 11025;
  200.                break;
  201.      case 22 : samp_rate = 22050;
  202.                break;
  203.      case 44 : samp_rate = 44100;
  204.                break;
  205.      default : samp_rate =  8000;
  206.     }
  207.  
  208.   if (bits != 16)
  209.      bits = 8;
  210.  
  211.   DosCreateEventSem(NULL,&sem,0,0);
  212.   tid = _beginthread(PlayThread,0,8096,0);
  213.   DosSetPriority(PRTYS_THREAD,PRTYC_TIMECRITICAL,1,tid);
  214.   
  215.   return (argc);
  216. }
  217.  
  218. void
  219. audio_term(void)
  220. {
  221.   DosPostEventSem(sem);
  222.   DosWaitThread(&tid,DCWW_WAIT);
  223.   DosCloseEventSem(sem);
  224. }
  225.  
  226. void
  227. audio_play(int n, short *data)
  228. {
  229.  ULONG rc;
  230.  
  231.  if (!quiet)
  232.   {
  233.  
  234.    if (bits == 8)
  235.      {
  236.        unsigned char *plabuf;
  237.  
  238.        plabuf = (unsigned char *) malloc(n);
  239.        if (plabuf)
  240.          {
  241.           unsigned char *p = plabuf;
  242.           unsigned char *e = p + n;
  243.           short temp;
  244.           while (p < e)
  245.             {
  246.              temp = *data / 128;
  247.              *p = temp + 128;
  248.              p++;
  249.              data++;
  250.             }
  251.           if(!List)
  252.              {
  253.                 List = (struct PlayDataList *)malloc(sizeof(struct PlayDataList));
  254.                 List->next = NULL;
  255.                 List->charbuff=plabuf;
  256.                 List->n = n;
  257.                 DosPostEventSem(sem);
  258.              }
  259.            else
  260.              {
  261.       struct PlayDataList *li = List;
  262.                 while(li->next)
  263.                      li=li->next;
  264.                 li->next=(struct PlayDataList *)malloc(sizeof(struct PlayDataList));
  265.                 li=li->next;
  266.                 li->next = NULL;
  267.                 li->charbuff=plabuf;
  268.                 li->n = n;
  269.                 DosPostEventSem(sem);
  270.              }
  271.  
  272.          }
  273.        else 
  274.          {
  275.            fprintf(stderr, "Insufficient memory for Play Buffer\n\n");
  276.            return;
  277.          }
  278.      }
  279.    else  /* if bits == 16 */
  280.      {
  281.       short *plabuf;
  282.  
  283.       plabuf = (short *) malloc(n * sizeof(short));
  284.       if (plabuf)
  285.          {
  286.           short *p = plabuf;
  287.           short *e = p + n;
  288.           while (p < e)
  289.             {
  290.              *p = *data;
  291.              p++;
  292.              data++;
  293.             }
  294.           if(!List)
  295.              {
  296.                 List = (struct PlayDataList *)malloc(sizeof(struct PlayDataList));
  297.                 List->next = NULL;
  298.                 List->shortbuff=plabuf;
  299.                 List->n = n;
  300.                 DosPostEventSem(sem);
  301.              }
  302.            else
  303.              {
  304.       struct PlayDataList *li = List;
  305.                 while(li->next)
  306.                      li=li->next;
  307.                 li->next=(struct PlayDataList *)malloc(sizeof(struct PlayDataList));
  308.                 li=li->next;
  309.                 li->next = NULL;
  310.                 li->shortbuff=plabuf;
  311.                 li->n = n;
  312.                 DosPostEventSem(sem);
  313.              }
  314.  
  315.          }
  316.        else 
  317.          {
  318.            fprintf(stderr, "Insufficient memory for Play Buffer\n\n");
  319.            return;
  320.          }
  321.      }
  322.   }
  323. }
  324.    
  325.  
  326.